<?php
/**
 * Paypal API
 *
 * This package provides access to the Paypal api
 *
 * @package		Clear Media Package
 * @author		Clear Media UK Ltd Dev Team
 * @copyright	Copyright (c) 2008 Clear Media UK.
 * @license		
 * @link		http://clearmediawebsites.co.uk
 * @since		Version 1.0
 * @filesource
 */
require_once('Paypal_api_transport.php');
/**
 * This class abstracts the Paypal api, the details of the api are
 * found here: https://cms.paypal.com/us/cgi-bin/?&cmd=_render-content&content_ID=developer/howto_api_reference
 *
 * @author		Clear Media UK Ltd Dev Team
 * @copyright	Copyright (c) 2008 Clear Media UK.
 * @license		
 * @link		http://clearmediawebsites.co.uk
 * @since		Version 1.0
 */
class Paypal_api extends Paypal_api_transport
{
	private $locale				= 'GB';		// This is the country code. Maybe needs an accessor method
	private $currency_code		= 'GBP';	// This is the currency code. Maybe needs an accessor method
	private $live_login_url		= 'https://www.paypal.com/webscr&cmd=_express-checkout&token=';			// Used for the redirect method, shouldn't need changing ever hopefully
	private $sandbox_login_url	= 'https://www.sandbox.paypal.com/webscr&cmd=_express-checkout&token=';	// Used for the redirect method, shouldn't need changing ever hopefully

	/**
	 * constructor just ensures we call our parent class
	 *
	 * @param void
	 * @return void
	 */
	public function __construct()
	{
		parent::__construct();
	}
	
    // --------------------------------------------  
	
	/**
	 * Initiates an Express checkout transaction
	 *
	 * Example use: set_express_checkout('10.00', 'http://example.com', 'http://example.com', 'http://example.com');
	 *
	 * @param float $amount the total amount of the order
	 * @param string $return_url the url to send a user to after payment is completed
	 * @param string $cancel_url the url to send a user to if they cancel
	 * @param string $callback_url the callback url for notifications
	 * @return void
	 * @todo there is more to do here to make sure this single function can be used for both one-off and recurring payments
	 * @todo add a parameter for the PAYMENTACTION
	 */	
	public function set_express_checkout($amount = '0.00', $return_url = '', $cancel_url = '', $description = '')
	{
		$method = 'SetExpressCheckout';
		
		$this->description = $description;
		
		$data = array(	
						'Amt' => number_format((float)$amount, 2),
						'ReturnUrl' => (string)$return_url,
						'CANCELURL' => (string)$cancel_url,
						'PAYMENTACTION' => 'Authorization',
						'CURRENCYCODE' => $this->currency_code,
						'LOCALECODE' => $this->locale,
						'L_BILLINGTYPE0' => 'RecurringPayments',
						'L_BILLINGAGREEMENTDESCRIPTION0' => $this->description,
						'ALLOWNOTE' => 1,
						'NOSHIPPING' => 1,
						);
		$this->execute_request($method, $data);
		return;
	}
	
    // --------------------------------------------  	

	/**
	 * Unused with versions 54 or above of the API, it's been superceeded by
	 * SetExpressCheckout, this is only included here because I was using a lower 
	 * version of the API to begin with, and it was written, therefore included
	 * 
	 * NOTE: DO NOT USE THIS FUNCTION
	 *
	 * @param string $return_url
	 * @param string $cancel_url
	 * @return void
	 * @todo remove this function?
	 */
	public function set_customer_billing_agreement($return_url = '', $cancel_url = '')
	{
		$method = 'SetCustomerBillingAgreement';
		$data = array(
						'RETURNURL' => (string)$return_url,
						'CANCELURL' => (string)$cancel_url,
						'LOCALECODE' => $this->locale,	
						'BILLINGTYPE' => 'RecurringPayments',
						);
		$this->execute_request($method, $data);
		return;		
	}
	
    // --------------------------------------------     	
	
	/**
	 * gets the express checkout details 
	 *
	 * @param (optional) string $token
	 * @return void
	 */
	public function get_express_checkout_details($token = '')
	{
		if( ! $token) {
			$token = $this->api_response_token;
		}
		
		$method = 'GetExpressCheckoutDetails';
		$data = array(
						'TOKEN' => $token,
						);
		$this->execute_request($method, $data);
		return;
	}
	
    // --------------------------------------------
	
	/**
	 * creates a recurring payments profile, have added some basic 
	 * error correction for incorrect values for the $billingperiod
	 *
	 * @param string (optional) $token
	 * @param string $profile_start_date MUST be UTC/GMT format
	 * @param string $description
	 * @param float $amount
	 * @param int $billingfreq the billing frequency
	 * @param string $billingperiod Day, Month, Year etc
	 * @return void
	 * @todo not sure, but still loads to do here I think
	 */
	public function create_recurring_payments_profile(	$token 				= '', 
														$profile_start_date = '',
														$description		= '', // MUST match the description set in set_express_checkout()!!
														$amount 			= 0,
														$billingfreq 		= 12,
														$billingperiod 		= 'Month')
	{
		$method = 'CreateRecurringPaymentsProfile';
		
		if( ! $token) {
			$token = $this->api_response_token;
		}
		
		$profile_start_date = date('Y-m-d\TH:i:s\Z', strtotime($profile_start_date)); 
		$amount 			= number_format((float)$amount, 2);
		$billingfreq		= (int)$billingfreq;
		$billingperiod		= ucfirst($billingperiod);
		
		// This checks the billingperiod is valid
		// if not, we default back to "month"
		// Also ensures we have a valid value for billingfreq
		switch($billingperiod) {
			case 'Day':		
				if($billingfreq > 365) {
					$billingfreq = 365;
				}
				break;
			case 'Daily':
				$billingperiod = 'Day';
				if($billingfreq > 365) {
					$billingfreq = 365;
				}
				break;					
			case 'Week':
				if($billingfreq > 52) {
					$billingfreq = 52;
				}
				break;
			case 'Weekly':
				$billingperiod = 'Week';
				if($billingfreq > 52) {
					$billingfreq = 52;
				}
				break;				
			case 'SemiMonth':		
				if($billingfreq > 1) {
					$billingfreq = 1;
				}
				break;
			case 'Month':		
				if($billingfreq > 12) {
					$billingfreq = 1;
				}
				break;
			case 'Monthly':
				$billingperiod = 'Month';
				if($billingfreq > 12) {
					$billingfreq = 1;
				}					
				break;
			case 'Year':
				if($billingfreq > 1) {
					$billingfreq = 1;
				}
				break;
			default:
				$billingperiod = 'Month';
				$billingfreq = 1;
				break;
		}	
		
		
		$data = array(
						'TOKEN' => $token,
						'PROFILESTARTDATE' => $profile_start_date,
						'DESC' => $description,
						'AMT' => $amount,	// Already number formatted above
						'BILLINGFREQUENCY' => $billingfreq,
						'BILLINGPERIOD' => $billingperiod,
						'CURRENCYCODE' => $this->currency_code,
						);
		$this->execute_request($method, $data);
		return;						
	}
	
    // --------------------------------------------   

	/**
	 * Allows us to cancel or suspend an order
	 *
	 * @param string $profile_id
	 * @param string $action cancel, suspend, reactivate
	 * @param string $note
	 */
	public function manage_recurring_payments_profile_status($profile_id, $action, $note)
	{
		$method = 'ManageRecurringPaymentsProfileStatus';	
		
		$data = array(
						'PROFILEID' => (string)$profile_id,
						'ACTION' => ucfirst((string)$action),
						'NOTE' => (string)$note,
						);
		$this->execute_request($method, $data);
		return;						
	}
	
    // --------------------------------------------     		

	/**
	 * Allows us to execute a DoExpressCheckoutPayment request
	 * This function is a worry, we're using the latest version of the API (63.0) but this function will
	 * only work using depreciated function calls, if Paypal decide to change things this function will likely break
	 * but what can you do???
	 *
	 * Ref: https://cms.paypal.com/us/cgi-bin/?&cmd=_render-content&content_ID=developer/e_howto_api_nvp_r_DoExpressCheckoutPayment
	 *
	 * @param string $token the paypal payment token
	 * @param string $payer_id (REQUIRED) as returned by GetExpressCheckoutDetails
	 * @param float $payment_amount (REQUIRED) basically a float of the amount, I think this must match the amount set in SetExpressCheckout
	 * @return void
	 * @todo add a parameter for the PAYMENT ACTION
	 */
	public function do_express_checkout_payment($token = '', $payer_id, $payment_amount)
	{
		if( ! $token) {
			$token = $this->api_response_token;
		}
		
		$method = 'DoExpressCheckoutPayment';
		
		$data = array(
						'TOKEN' => $token,
						'PAYERID' => $payer_id,
						'AMT' => number_format((float)$payment_amount, 2),	// The docs state you need to use PAYMENTREQUEST_n_AMT but that fails...
						'PAYMENTACTION' => 'Sale',	// The docs state you need to use PAYMENTREQUEST_n_PAYMENTACTION but that fails...
						'CURRENCYCODE' => $this->currency_code, // Not even in the docs...?
						);
		$this->execute_request($method, $data);
		return;						
	}
	
    // --------------------------------------------    

	/**
	 *
	 *
	 *
	 */
	public function get_recurring_payments_profile_details($paypal_profile_id = '')
	{
		// We must have a profile id!
		if( ! $paypal_profile_id) {
			return false;
		}
		
		$method = 'GetRecurringPaymentsProfileDetails';
		$data = array(
						'PROFILEID' => $paypal_profile_id,
						);
		$this->execute_request($method, $data);
		return;		
	}
	
    // -------------------------------------------- 

	/**
	 * This one's not in the official PAYPAL API, it's a utility 
	 * for me, it allows you change the amount of a recurring payment
	 * 
	 * NOTE: you MUST NOT increase the AMT by more than 20% every 180 days
	 *		that's up to you to monitor!!!
	 *
	 * @param string $paypal_profile_id
	 * @param float $amount
	 * @return void
	 * @access public
	 * @todo create a FULL version of UpdateRecurringPaymentsProfile
	 */
	public function change_payment_amt($paypal_profile_id = '', $amount = 0)
	{
		// We must have a profile id!
		if( ! $paypal_profile_id) {
			return false;
		}

		$method = 'UpdateRecurringPaymentsProfile';
		$data = array(
						'PROFILEID' => $paypal_profile_id,
						'AMT' => number_format((float)$amount, 2),
						'CURRENCYCODE' => $this->currency_code, // Again, not even in the docs...
						);
						
		$this->execute_request($method, $data);
		return;							
	}
	
    // --------------------------------------------  	
		

	/**
	 * Accessors-----------------------------------
	 */

	/**
	 * Returns the Paypal API response token
	 *
	 * @param void
	 * @return string
	 */
	public function get_token()
	{
		return $this->api_response_token;
	}
	
    // --------------------------------------------     		

	/**
	 * sets the mode of the api, only value you can
	 * pass that will be used is 'debug'
	 *
	 * @param string $mode
	 * @return void
	 */
	public function set_debug_mode($mode = 'live')
	{
		if(strtolower($mode) == 'debug') {
			$this->debug = true;
		}
		
		return;
	}
	
    // --------------------------------------------    
	
	/**
	 * redirects users to the Paypal login pages
	 *
	 * @param
	 * @return void
	 */
	public function redirect($paypal_api_token = '')
	{
		if(strtoupper($this->mode) != 'LIVE') {
			header('Location: ' . $this->sandbox_login_url . $paypal_api_token);
		} else {
			header('Location: ' . $this->live_login_url . $paypal_api_token);
		}
	}
	
    // --------------------------------------------   

	/**
	 * gets the result of the api request as a bool
	 *
	 * @param void
	 * @return bool
	 */
	public function get_result()
	{
		return (strtolower($this->result) == 'success') ? true : false;
	}
	
    // -------------------------------------------- 

	/**
	 * returns the last error code
	 *
	 * @param void
	 * @return string
	 */
	public function get_error()
	{
		return $this->error;
	}
	
    // --------------------------------------------

	/**
	 * gets a recurring payments profile id
	 *
	 * @param void
	 * @return string
	 */
	public function get_profile_id()
	{
		return $this->profile_id;
	}
	
    // --------------------------------------------   
  	
	/**
	 * gets a payer id
	 *
	 * @param void
	 * @return string
	 */
	public function get_payer_id()
	{
		return $this->payer_id;
	}
	
    // --------------------------------------------  

	/**
	 * returns the last payment date
	 *
	 * @param void
	 * @return string
	 */
	public function get_last_payment_date()
	{
		return $this->last_payment_date;
	}
	
    // --------------------------------------------  	

	/**
	 * returns the last payment amount
	 *
	 * @param void
	 * @return float
	 */
	public function get_last_payment_amount()
	{
		return $this->last_payment_amount;
	}
	
    // -------------------------------------------- 
	
	/**
	 * returns the last payment status
	 *
	 * @param void
	 * @return float
	 */
	public function get_status()
	{
		return $this->status;
	}
	
    // --------------------------------------------  				   	
		
}
